/**************************************************************************
 *  Copyright (C) 2008 - 2010 by Simon Qian                               *
 *  SimonQian@SimonQian.com                                               *
 *                                                                        *
 *  Project:    Versaloon                                                 *
 *  File:       GPIO.h                                                    *
 *  Author:     SimonQian                                                 *
 *  Versaion:   See changelog                                             *
 *  Purpose:    GPIO interface header file                                *
 *  License:    See license                                               *
 *------------------------------------------------------------------------*
 *  Change Log:                                                           *
 *      YYYY-MM-DD:     What(by Who)                                      *
 *      2008-11-07:     created(by SimonQian)                             *
 **************************************************************************/
#include "vsf.h"

#define VSFHAL_GPIO_NUM					7

vsf_err_t vsfhal_gpio_init(uint8_t index)
{
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN << index;
	return VSFERR_NONE;
}

vsf_err_t vsfhal_gpio_fini(uint8_t index)
{
	RCC->APB2ENR &= ~(RCC_APB2ENR_IOPAEN << index);
	RCC->APB2RSTR &= ~(RCC_APB2RSTR_IOPARST << index);
	return VSFERR_NONE;
}

vsf_err_t vsfhal_gpio_config(uint8_t index, uint8_t pin_idx, uint32_t mode)
{
	GPIO_TypeDef *gpio;
	uint32_t tmpreg = mode & 0x0F;

	gpio = (GPIO_TypeDef *)(GPIOA_BASE + ((uint32_t)index << 10));
	if(pin_idx < 8)
	{
		gpio->CRL = (gpio->CRL & ~(((uint32_t)0x0F) << ((pin_idx - 0) * 4))) | 
						tmpreg << ((pin_idx - 0) * 4);
	}
	else
	{
		gpio->CRH = (gpio->CRH & ~(((uint32_t)0x0F) << ((pin_idx - 8) * 4))) | 
						tmpreg << ((pin_idx - 8) * 4);
	}
	
	if(0x08 == tmpreg)
	{
		if(mode & 0x80)
			gpio->BSRR = (1UL << pin_idx);
		else
			gpio->BRR = (1UL << pin_idx);
	}
	return VSFERR_NONE;
}

vsf_err_t vsfhal_gpio_set(uint8_t index, uint32_t pin_mask)
{
	GPIO_TypeDef *gpio = (GPIO_TypeDef *)(GPIOA_BASE + ((uint32_t)index << 10));
	gpio->BSRR = pin_mask;
	return VSFERR_NONE;
}

vsf_err_t vsfhal_gpio_clear(uint8_t index, uint32_t pin_mask)
{
	GPIO_TypeDef *gpio = (GPIO_TypeDef *)(GPIOA_BASE + ((uint32_t)index << 10));
	gpio->BRR = pin_mask;
	return VSFERR_NONE;
}

vsf_err_t vsfhal_gpio_out(uint8_t index, uint32_t pin_mask, uint32_t value)
{
	GPIO_TypeDef *gpio = (GPIO_TypeDef *)(GPIOA_BASE + ((uint32_t)index << 10));
	gpio->BSRR = pin_mask & value;
	gpio->BRR = pin_mask & ~value;
	return VSFERR_NONE;
}

uint32_t vsfhal_gpio_get(uint8_t index, uint32_t pin_mask)
{
	GPIO_TypeDef *gpio = (GPIO_TypeDef *)(GPIOA_BASE + ((uint32_t)index << 10));
	return gpio->IDR & pin_mask;
}
